package com.shen.shenproject.coroutine

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.lifecycleScope
import com.shen.shenproject.R
import com.shen.shenproject.coroutine.retrofit.Repo
import com.shen.shenproject.coroutine.retrofit.RetrofitApi
import io.reactivex.SingleObserver
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.activity_coroutine.*
import kotlinx.coroutines.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.lang.Exception
import java.util.concurrent.LinkedBlockingDeque
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit

/**
 * 协程
 */
class CoroutineActivity : AppCompatActivity() {


    var job : Job? = null

    private val scope = MainScope()

    init {
        // 当 onCreated 被执行后才执行
        lifecycleScope.launchWhenCreated{

        }

        // 当 onResumed 被执行后才执行
        lifecycleScope.launchWhenResumed{

        }
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_coroutine)

        GlobalScope.launch(Dispatchers.Main){// Dispatchers.Main -- 添加这个 说明这个协程是 在主线程运行 （默认是在 io线程）
            ioCode1()
            uiCode1()
        }

        classicIoCode1(false){
            uiCode1()
        }

        classicIoCode2(false){
            uiCode1()
        }

        job = GlobalScope.launch(Dispatchers.Main){// Dispatchers.Main -- 添加这个 说明这个协程是 在主线程运行 （默认是在 io线程）
            retrofitCoroutineDemo1()
        }

        scope.launch {
            retrofitCoroutineDemo1()
        }

        // 这个是依赖于     implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0'
        // 在 onDestroy 会自动帮我们取消 这个协程
        lifecycleScope.launch{

        }


    }

    private suspend fun ioCode1(){
        withContext(Dispatchers.IO){ // Dispatchers.IO -- 添加这个 说明这段代码 在io线程
            println("Coroutines Camp: ioCode1() ${Thread.currentThread().name}")
        }
    }

    private fun uiCode1(){
        println("Coroutines Camp: uiCode1() ${Thread.currentThread().name}")
    }

    private val executor = ThreadPoolExecutor(5, 20, 1,
        TimeUnit.MINUTES, LinkedBlockingDeque())

    private fun classicIoCode1(isUiThread: Boolean, block:() -> Unit){
        executor.execute{
            println("Coroutines Camp: classicIoCode1() ${Thread.currentThread().name}")
            if(isUiThread){
                block()
            } else{
                runOnUiThread {
                    block()
                }
            }
        }
    }

    private fun classicIoCode2(isUiThread: Boolean, block:() -> Unit){
        executor.execute{
            println("Coroutines Camp: classicIoCode1() ${Thread.currentThread().name}")
            if(isUiThread){
                block()
            } else{
                runOnUiThread {
                    block()
                }
            }
        }
    }

    /**
     * Retrofit + OkHttp
     */
    private fun retrofitDemo(){
        val retrofit = Retrofit.Builder()
            .baseUrl("https://api.github.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        val api = retrofit.create(RetrofitApi::class.java)

        api.listRepos("rengwuxian")
            .enqueue(object : Callback<List<Repo>?>{
                override fun onResponse(call: Call<List<Repo>?>, response: Response<List<Repo>?>) {
                    tv_name.text = response.body()?.get(0)?.name
                }
                override fun onFailure(call: Call<List<Repo>?>, t: Throwable) {

                }
            })
    }

    /**
     * Retrofit + OkHttp + RxJava
     */
    private fun retrofitRxDemo(){
        val retrofit = Retrofit.Builder()
            .baseUrl("https://api.github.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        val api = retrofit.create(RetrofitApi::class.java)

        api.listReposRx("rengwuxian")
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : SingleObserver<List<Repo>>{

                override fun onSubscribe(d: Disposable) {
                    tv_name.text = "开始加载"
                }

                override fun onError(e: Throwable) {
                    tv_name.text = e.message
                }

                override fun onSuccess(t: List<Repo>) {
                    tv_name.text = t[0].name
                }
            })
    }

    /**
     * Retrofit + OkHttp + 协程
     */
    private suspend fun retrofitCoroutineDemo1(){
        val retrofit = Retrofit.Builder()
            .baseUrl("https://api.github.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        val api = retrofit.create(RetrofitApi::class.java)

        val repo = api.listReposKt("rengwuxian")
        tv_name.text = repo[0].name

    }


    /**
     * Retrofit + OkHttp + 协程    多任性执行 都完成后才往下走
     *
     * async{} -》  同时进行 -- 放在 协程里面
     * await() -》 将整个协程 挂起 直到执行完
     */
    private suspend fun retrofitCoroutineDemo2(){
        val retrofit = Retrofit.Builder()
            .baseUrl("https://api.github.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        val api = retrofit.create(RetrofitApi::class.java)

        GlobalScope.launch(Dispatchers.Main){// Dispatchers.Main -- 添加这个 说明这个协程是 在主线程运行 （默认是在 io线程）
            try{
                val asyncRepos1 = async{ api.listReposKt("rengwuxian") }
                val asyncRepos2 = async{ api.listReposKt("goole") }
                val repo = "${asyncRepos1.await()[0].name} -》 ${asyncRepos2.await()[0].name}"   // 两个都要执行完
                tv_name.text = repo
            }catch (e: Exception){
                tv_name.text = e.message
            }
        }
    }


    override fun onDestroy() {
        super.onDestroy()
        job?.cancel()           // 取消协程
        scope.cancel()          // 取消协程
    }
}
